from server import db, app_auth, user_opt
from flask import jsonify, Blueprint, request, g, make_response
from server.model.app_user import AppUser
from server.model import set_field
import requests
import emoji
import re
from os import getenv

a_app_user = Blueprint('app/app_user', __name__)


@app_auth.verify_token
def verify_token(token):
    if not token:
        return False

    user = AppUser.verify_auth_token(token)
    if not user:
        return False
    g.user = user
    g.user.user_type = 'app_user'
    return True


@app_auth.error_handler
def unauthorized():
    return make_response(jsonify({'error': 'Unauthorized access'}), 401)


# 获取受理员
@a_app_user.route('/get_acceptor', methods=['GET'])
def get_acceptor():
    try:
        acceptors = AppUser.query.filter(AppUser.role == 'acceptor').all()

        return jsonify({
            'code': 200,
            'items': [u.to_dict() for u in acceptors]
        })

    except Exception as e:
        db.session.rollback()

    return jsonify({'code': 50001, 'message': "获取受理员发生错误"})


@a_app_user.route('/login', methods=['GET'])
def user_login():
    """
        @@@
        #### Args:
                code = request.args.get('code')
        #### Returns::
                {
                    'code': 200,
                    'user_id': g.user.id,
                    'nick_name': g.user.nick_name,
                    "token": token.decode(),
                }
                {
                    'code': 500,
                    'msg': "code失效或不正确"
                }
    """
    code = request.args.get('code')
    print("doing login..", code)

    params = {
        'appid': getenv('WECHAT_APPID'),
        'secret': getenv('WECHAT_SECRET'),
        'js_code': code,
        'grant_type': 'authorization_code'
    }
    wx_login_api = 'https://api.weixin.qq.com/sns/jscode2session'
    resp = requests.get(wx_login_api, params=params)
    data = resp.json()
    print("got login info :", data)
    if 'errcode' in data:
        return {
            'code': 500,
            'msg': "授权失败, 错误信息:%s " % data['errmsg']
        }
    openid = data['openid']
    session_key = data['session_key']
    print("---session:", session_key)
    if openid and session_key:
        user_info = AppUser.query.filter(AppUser.open_id == openid).first()

        if user_info is None:
            user_info = AppUser(open_id=openid)
            db.session.add(user_info)
        user_info.session_key = session_key
        db.session.commit()
        g.user = user_info
        token = user_info.generate_auth_token()
        return jsonify({
            'code': 20000,
            "item": user_info.to_dict(),
            "token": "Bearer %s" % token.decode(),
        })
    return jsonify({
        'code': 50001,
        'msg': "code失效或不正确"
    })


@a_app_user.route('/upload_info', methods=['POST'])
@app_auth.login_required
def upload_user_info():
    """
        @@@
        #### Args:
                user_info = request.json['user_info']
        #### Returns::
                {'code': 200, 'msg': 'ok'}
    """
    user_info = request.json['user_info']
    print("upload_info--", user_info)
    nick_name = user_info.get('nickName')
    if nick_name:
        name = emoji.demojize(nick_name)
        name = re.sub(r':(.+?):', '', name).strip()
        print("got name:", name)
        g.user.nick_name = name
    g.user.head_url = user_info['avatarUrl']
    db.session.commit()
    return jsonify({'code': 20000, 'msg': 'ok'})


@a_app_user.route('/upload_phone', methods=['POST'])
@app_auth.login_required
def upload_phone():
    """
        @@@
        #### Args:
                encryptedData
                iv
        #### Returns::
                {'code': 200, 'msg': 'ok'}
    """
    import base64
    from Crypto.Cipher import AES
    import json
    app_user = g.user
    args = request.json
    encrypted_data = args.get('encryptedData')
    iv = args.get('iv')
    app_id = getenv('WECHAT_APPID')
    session_key = app_user.session_key
    print(">>>>>", args, app_id, session_key)
    try:
        def unpad(s):
            return s[:-ord(s[len(s) - 1:])]

        # base64 decode
        session_key = base64.b64decode(session_key)
        encrypted_data = base64.b64decode(encrypted_data)
        iv = base64.b64decode(iv)
        cipher = AES.new(session_key, AES.MODE_CBC, iv)
        unpack_result = unpad(cipher.decrypt(encrypted_data))
        print(">>>>>", type(unpack_result))
        try:
            decrypted = json.loads(unpack_result)
            if decrypted['watermark']['appid'] != app_id:
                print('Invalid Buffer')
        except Exception as e:
            print("not a json format")
            return jsonify({'code': 50002, 'msg': '获取手机号失败,请联系管理员'})

        phone_num = decrypted.get('phoneNumber')
        if not phone_num:
            return jsonify({'code': 50002, 'msg': '获取手机号失败,请联系管理员'})

        print("got the phone:", app_user.phone, bool(app_user.phone))
        app_user.phone = phone_num
        db.session.commit()

        return jsonify({'code': 20000, 'phone': phone_num})
    except Exception as e:
        db.session.rollback()
        print("get app user phone error", e)

    return jsonify({'code': 50001, 'message': "获取手机号失败时发生错误"})


@a_app_user.route('/<int:pid>', methods=['PUT'])
@app_auth.login_required
def edit_app_user(pid):
    """
    @@@
    #### Args:
           app_user/id
    #### Returns::
            {'code': 20000, 'message': "app用户修改成功"}
            {'code': 50001, 'message': "修改app用户时发生错误"}
    """
    args = request.get_json()
    try:
        app_user = AppUser.query.filter_by(id=g.user.id).first()
        set_field(app_user, args, include=('nick_name', 'phone', 'subscribe_on'))

        db.session.commit()

        user_opt.send({
            "operation": "修改app用户",
            "method": "app用户管理",
            "params": pid,
            "user_id": g.user.id,
        })

        return jsonify({'code': 20000, 'message': "app用户修改成功"})
    except Exception as e:
        db.session.rollback()
        print("edit app_user error:", e)

    return jsonify({'code': 50001, 'message': "修改app用户时发生错误"})


@a_app_user.route('', methods=['GET'])
@app_auth.login_required
def get_detail():
    return jsonify({
        'code': 20000,
        'message': 'success',
        'info': g.user.to_dict(exclude={"password"}),
    })

# >>>>> auto generate end <<<<<
